package com.cash.channel.api.model.channel;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

@Setter
@Getter
@Slf4j
public class RequireParam implements Serializable {

    public static final String ROOT = "ROOT";

    private Boolean isParent;

    private String paramName;

    private RequireParam parentParam;

    private RequireParam rootParam;

    private Map<String, RequireParam> subParams;

    private Set<RequireParam> parentSubParam;

    public static RequireParam init() {
        return new RequireParam(null,true, ROOT);
    }

    RequireParam(RequireParam parentParam,Boolean isParent, String paramName) {
        this.isParent = isParent;
        this.paramName = paramName;
        this.subParams = Maps.newHashMap();
        this.parentSubParam = Sets.newHashSet();
        this.parentParam = parentParam;
        this.rootParam = parentParam==null?this: this.rootParam;
    }

    public RequireParam appendSubRequireParam(Boolean isParent, String paramName) {
        if (subParams.containsKey(paramName)) {
            return MapUtils.getObject(subParams, paramName);
        }
        RequireParam requireParam = new RequireParam(this ,isParent, paramName);
        if (isParent) {
            this.parentSubParam.add(requireParam);
        }
        this.subParams.put(paramName, requireParam);
        return requireParam;
    }

    public RequireParam findRequireParam(String paramName, Boolean allowNull) {
        RequireParam requireParam = subParams.get(paramName);
        if (!allowNull&&requireParam==null) {
            throw new RuntimeException("未找到["+paramName+"]必填字段");
        }
        return requireParam;
    }

    public RequireParam findRequireParam(String paramName) {
        return findRequireParam(paramName, true);
    }

    public Set<String> subKeys() {
        return this.subParams.keySet();
    }

    public Set<RequireParam> parentSubParams() {
        return this.parentSubParam;
    }

    public RequireParam getRoot() {
        return this.rootParam;
    }

    public boolean isRoot() {
        return ROOT.equalsIgnoreCase(this.paramName);
    }

    @Override
    public String toString() {
        return "RequireParam{" +
                "isParent=" + isParent +
                ", paramName='" + paramName + '\'' +
                ", subParams=" + subParams +
                '}';
    }
}
